#include "log.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <iomanip>
#include <ctime>


logger& logger::get_instance()
{
	static logger instance;
	return instance;
}

logger::logger()
	: log_file_path("myapp.log")
	, console_enabled(true)
	, file_enabled(true)
{
}

void logger::log(log_level level, const std::string& message, const char* file_name, int line_number)
{
	std::string timestamp = get_current_timestamp();
	std::string levelStr = get_level_string(level);
	std::string colorCode = get_level_color(level);

	std::string logMessage = timestamp + " [" + file_name + ":" +
		std::to_string(line_number) + "] [" + levelStr + "] " + message;

	if (console_enabled)
	{
		std::cout << colorCode << logMessage << "\033[0m" << "\n";
	}

	if (file_enabled)
	{
		std::ofstream log_file(log_file_path, std::ios_base::app);
		if (log_file.is_open())
		{
			log_file << logMessage << "\n";
			log_file.close();
		}
		else
		{
			std::cerr << "Failed to open log file: " << log_file_path << "\n";
		}
	}
}

void logger::set_log_file(const std::string& filename)
{
	log_file_path = filename;
}

void logger::enable_console(bool enable)
{
	console_enabled = enable;
}

void logger::enable_file(bool enable)
{	file_enabled = enable;}

std::string logger::get_current_timestamp()
{
	auto now = std::chrono::system_clock::now();
	std::time_t now_time = std::chrono::system_clock::to_time_t(now);
		std::tm ltm;
	localtime_s(&ltm, &now_time);

	std::ostringstream oss;
	oss << std::put_time(&ltm, "%Y-%m-%d %X");
	return oss.str();
}

std::string logger::get_level_string(log_level level)
{
	switch (level)
	{
	case log_level::debug:   return "DEBUG";
	case log_level::info:    return "INFO";
	case log_level::warning: return "WARNING";
	case log_level::error:   return "ERROR";
	default:                 return "UNKNOWN";
	}
}

std::string  logger::get_level_color(log_level level)
{
	switch (level)
	{
	case log_level::debug:   return "\033[1;32m";
	case log_level::info:    return "\033[1;34m";
	case log_level::warning: return "\033[1;33m";
	case log_level::error:   return "\033[1;31m";
	default:                 return "\033[0m";
	}
}
